import { _decorator, AnimationState, BoxCollider, Camera, CapsuleCollider, Component, director, easing, instantiate, ITriggerEvent, log, MeshRenderer, Node, Prefab, quat, Quat, resources, RigidBody, SkeletalAnimation, Tween, tween, v3, Vec3 } from 'cc';
import { GameManager, Group } from './Manager/GameManager';
import { UIManager } from './Manager/UIManager';
import { Card } from './Card';
import { Monster } from './Monster';
import { PlayerController } from './Manager/PlayerController';
import { ZTool } from './Manager/ZTool';
import { AudioManager } from './Manager/AudioManager';
import Banner from './Manager/Banner';
const { ccclass, property } = _decorator;

const quat_rota = quat();
const v3_dir = v3();

@ccclass('Player')
export class Player extends Component {

    private static _instance: Player = null;
    public static get Instance(): Player {
        if (!this._instance) {
            this._instance = new Player();
        }
        return this._instance;
    }

    PlayerRigibody: RigidBody;
    PlayerAni: SkeletalAnimation;

    HaveMonsters = [];
    IsDead: boolean = false;

    onLoad() {
        Player._instance = this;
        this.PlayerRigibody = this.node.getComponent(RigidBody);
        this.PlayerAni = this.node.getComponentInChildren(SkeletalAnimation);
        this.PlayerAni.on(SkeletalAnimation.EventType.FINISHED, this.AniFinished, this);
        let collider = this.node.getComponent(CapsuleCollider);
        collider.on("onTriggerEnter", this.OnTriggerEnter, this);
        GameManager.Instance.MainCamera.setParent(this.node);
    }

    AniFinished(type, state: AnimationState) {
        switch (state.clip.name) {
            case "Back":
                {
                    this.CanRun = true;
                    this.PlayerAni.crossFade("Run");
                    PlayerController.Instance.TakeOnTouch();
                }
                break;
            case "Dead":
                {
                    UIManager.Instance.ShowFailedPanel();
                }
                break;
        }
    }

    playerFightPos = v3();
    start() {
        this.PlayerAni.crossFade("Idle");
    }

    CanRun: boolean = true;
    update(deltaTime: number) {
        if (GameManager.Instance.IsStart && !GameManager.Instance.IsEnterFight && this.CanRun) {
            this.PlayerRigibody.setLinearVelocity(v3(0, 0, -4));
        }

        if (GameManager.Instance.IsRunToArea) {
            Vec3.subtract(v3_dir, this.playerFightPos, this.node.getWorldPosition());
            this.PlayerRigibody.setLinearVelocity(v3_dir.normalize().multiplyScalar(10));
            if (Vec3.distance(this.playerFightPos, this.node.getWorldPosition()) <= 0.2) {
                GameManager.Instance.IsRunToArea = false;
                this.PlayerRigibody.setLinearVelocity(Vec3.ZERO);
                this.node.getComponent(CapsuleCollider).enabled = false;
                this.PlayerAni.crossFade("Idle");

                UIManager.Instance.Fight.getChildByName("FightLeft").children[GameManager.Instance.PlayerID].active = true;
                if (GameManager.Instance.GetLocalStorage("Level") < 5) {
                    UIManager.Instance.Fight.getChildByName("FightRight").children[0].active = true;
                }
                else {
                    if (GameManager.Instance.GetLocalStorage("Level") < 10) {
                        UIManager.Instance.Fight.getChildByName("FightRight").children[1].active = true;
                    }
                    else {
                        UIManager.Instance.Fight.getChildByName("FightRight").children[2].active = true;
                    }
                }
                UIManager.Instance.Running.active = false;
                UIManager.Instance.Fight.active = true;

                let mainCamera = GameManager.Instance.MainCamera;
                PlayerController.Instance.v3_TargetCameraPos.set(0, mainCamera.position.y + 8, mainCamera.position.z - 6);
                PlayerController.Instance.v3_TargetCameraAg.set(-80, 0, 0);
                tween(GameManager.Instance.FinishEnv)
                    .to(2, { position: v3(0, 5.5, GameManager.Instance.FinishEnv.position.z) }, { easing: "backOut" })
                    .call(() => {
                        GameManager.Instance.IsStart = false;
                        GameManager.Instance.ShowFightCard();
                        if (GameManager.Instance.GetLocalStorage("Level") == 4 || GameManager.Instance.GetLocalStorage("Level") == 9 || GameManager.Instance.GetLocalStorage("Level") == 14) {
                            GameManager.Instance.ShowBossFightCard();
                        }
                        else {
                            switch (GameManager.Instance.FinishEnv.children.length) {
                                case 2:
                                    {
                                        GameManager.Instance.ShowEnemyFightCard(0);
                                        this.scheduleOnce(() => {
                                            GameManager.Instance.ShowEnemyFightCard(1);
                                        }, 1)
                                    }
                                    break;
                                case 3:
                                    {
                                        GameManager.Instance.ShowEnemyFightCard(0);
                                        this.scheduleOnce(() => {
                                            GameManager.Instance.ShowEnemyFightCard(1);
                                            this.scheduleOnce(() => {
                                                GameManager.Instance.ShowEnemyFightCard(2);
                                            }, 1)
                                        }, 1)
                                    }
                                    break;
                            }
                        }
                    })
                    .start();
            }
        }
    }

    TurnAngleByEuler(angle: number, duration: number = 0.2) {
        quat_rota.set(this.node.getChildByName("Model").rotation);
        let rota = quat();
        Quat.fromEuler(rota, 0, angle, 0);
        Quat.lerp(quat_rota, quat_rota, rota, duration);
        this.node.getChildByName("Model").setRotation(quat_rota);
    }

    CanTrigger: boolean = true;
    TriggerNum: number = 0;
    OnTriggerEnter(event: ITriggerEvent) {
        if (event.otherCollider.node.name == "EndPoint") {
            this.playerFightPos = GameManager.Instance.EndArea.getChildByName("PlayerFightPos").getWorldPosition();
            GameManager.Instance.IsEnterFight = true;
            PlayerController.Instance.TakeOffTouch();
            PlayerController.Instance.deltaX = 0;
            event.otherCollider.node.getComponent(BoxCollider).enabled = false;
            for (let i in this.HaveMonsters) {
                this.HaveMonsters[i].getComponent(Monster).Following = false;
                this.HaveMonsters[i].getComponent(CapsuleCollider).enabled = false;
            }
            let mainCamera = GameManager.Instance.MainCamera;
            PlayerController.Instance.v3_TargetCameraPos.set(0, mainCamera.position.y - 3, mainCamera.position.z - 1);
            PlayerController.Instance.v3_TargetCameraAg.set(-5, 0, 0);
            GameManager.Instance.IsRunToArea = true;
        }
        if (event.otherCollider.node.name == "wandao") {
            event.otherCollider.enabled = false;
            tween(GameManager.Instance.RoadInit)
                .to(3, { eulerAngles: v3(0, -90, 0) }, { easing: "quadOut" })
                .start()
        }
        if (event.otherCollider.getGroup() == Group.Money) {
            AudioManager.Instance.playSound("Audio/Pop");
            if (event.otherCollider.node.scale.x == 1) {
                UIManager.Instance.AddMoneyNum(60);
            }
            else {
                UIManager.Instance.AddMoneyNum(180);
            }
            event.otherCollider.node.destroy();
        }
        if (event.otherCollider.getGroup() == Group.Card && this.CanTrigger) {
            if (event.otherCollider.node.getComponent(Card).CardTop.getChildByName("Video").active) {
                Banner.Instance.ShowVideo(this.InitMonster, event.otherCollider.node);
                return;
            }
            if (GameManager.Instance.MoneyNum < event.otherCollider.node.getComponent(Card).PriceValue) {
                if (!this.IsDead) {
                    if (GameManager.Instance.MoneyNum <= 0) {
                        PlayerController.Instance.TakeOffTouch();
                        this.CanRun = false;
                        this.IsDead = true;
                        this.PlayerRigibody.setLinearVelocity(Vec3.ZERO);
                        this.PlayerAni.crossFade("Dead");
                        for (let i in this.HaveMonsters) {
                            this.HaveMonsters[i].getComponent(Monster).MonsterAni.crossFade("Idle");
                        }
                    }
                    else {
                        this.PlayerAni.crossFade("Back");
                        PlayerController.Instance.TakeOffTouch();
                        PlayerController.Instance.deltaX = 0;
                        this.CanRun = false;
                        this.PlayerRigibody.setLinearVelocity(v3(0, 0, 1.5));
                        UIManager.Instance.SubMoneyNum(event.otherCollider.node.getComponent(Card).PriceValue / 3);
                    }
                }
            }
            else {
                UIManager.Instance.SubMoneyNum(event.otherCollider.node.getComponent(Card).PriceValue);
                this.InitMonster(event.otherCollider.node);
                this.TriggerNum++;
                if (this.TriggerNum >= 2) {
                    Banner.Instance.ShowNativeAd();
                    this.TriggerNum = 0;
                }
            }
        }
    }


    InitMonster(card: Node) {
        AudioManager.Instance.playSound("Audio/Init");
        Player.Instance.CanTrigger = false;
        setTimeout(() => {
            Player.Instance.CanTrigger = true;
        }, 1000)
        card.getComponent(Card).CardRole.active = false;
        card.getComponent(Card).CardTop.active = false;
        card.getChildByName("Card").getChildByName("Star2").active = false;
        card.getChildByName("Card").getChildByName("Star3").active = false;
        GameManager.Instance.SetLocalStorage(card.getComponent(Card).Name, 1);
        let initOffset = v3();
        switch (Player.Instance.HaveMonsters.length) {
            case 0:
                {
                    initOffset.set(- 1, 0, 0);
                }
                break;
            case 1:
                {
                    initOffset.set(1, 0, 0);
                }
                break;
            case 2:
                {
                    initOffset.set(0.5, 0, 1);
                }
                break;
            case 3:
                {
                    initOffset.set(-0.5, 0, 1);
                }
                break;
            case 4:
                {
                    initOffset.set(-1.5, 0, 1.2);
                }
                break;
            case 5:
                {
                    initOffset.set(1.5, 0, 1.2);
                }
                break;
        }
        let worldPos = Player.Instance.node.getWorldPosition();
        Tween.stopAllByTarget(card);
        tween(card)
            .to(0.3, { worldPosition: v3(worldPos.x + initOffset.x, 0, worldPos.z + initOffset.z - 2), eulerAngles: v3(-90, 0, 0), scale: Vec3.ONE })
            .call(() => {
                resources.load("Prefabs/Monster/" + card.getComponent(Card).Name, Prefab, (err, pre) => {
                    let monster = instantiate(pre);
                    monster.setParent(GameManager.Instance.MonsterInit);
                    monster.getComponent(Monster).MonsterAni.crossFade("Jump");
                    monster.setWorldPosition(v3(worldPos.x + initOffset.x, 0, worldPos.z + initOffset.z - 2));
                    monster.getComponent(Monster).FollowOffset = initOffset;
                    monster.getComponent(Monster).PowerValue = card.getComponent(Card).PriceValue;
                    monster.getComponent(Monster).Name = card.getComponent(Card).Name;
                    for (let i = 0; i < Player.Instance.HaveMonsters.length; i++) {
                        if (Player.Instance.HaveMonsters[i].name == monster.name) {
                            monster.getComponent(Monster).NeedHeCheng = true;
                            monster.getComponent(Monster).FollowOffset = Player.Instance.HaveMonsters[i].getComponent(Monster).FollowOffset;
                            monster.getComponent(CapsuleCollider).isTrigger = false;
                        }
                    }
                    Player.Instance.HaveMonsters.push(monster);
                    let cardInit = GameManager.Instance.Level.getChildByName("CardInit") ? GameManager.Instance.Level.getChildByName("CardInit") : GameManager.Instance.RoadInit.getChildByName("CardInit");
                    for (let i = 0; i < cardInit.children.length; i++) {
                        if (monster.name == cardInit.children[i].getComponentInChildren(Card).Name) {
                            cardInit.children[i].getChildByName("Card").getComponentInChildren(MeshRenderer).getMaterialInstance(0).setProperty("rimLightStrengthen", 10);
                            cardInit.children[i].getChildByName("Card").getChildByName("Card").getChildByName("Star2").active = true;
                        }
                    }
                })
            })
            .delay(0.5)
            .to(0.3, { scale: Vec3.ZERO }, { easing: "backIn" })
            .start()
    }
}


